﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace UmlControlLibrary
{
    public class UmlPackage : UmlElement
    {
        ObservableCollection<UmlElement> _childs = new ObservableCollection<UmlElement>();

        public override ObservableCollection<UmlElement> GetChilds()
        {
            return _childs;
        }  

        public bool Contains(string elementName)
        {
            if (elementName.StartsWith(this.Name + "."))
                elementName = elementName.Substring(this.Name.Length + 1);
            return Childs.Count(e => e.Name == elementName) > 0;
        }
        public UmlElement GetElement(string elementName)
        {
            if (Contains(elementName))
                return Childs.First(e => e.Name == elementName);
            else
                return null;
        }

        public void MergePackage(UmlPackage p)
        {
            foreach (UmlElement e in p.Childs)
            {
                if (e is UmlPackage)
                {
                    UmlPackage p2 = GetPackage(e.Name);
                    p2.MergePackage((UmlPackage)e);
                }
                else
                    AddElement(e);
            }
        }

        public UmlPackage GetPackage(string path)
        {
            string packageName;
            int i = path.IndexOf('.');
            if (i >= 0)
            {
                packageName = path.Substring(0, i);
                path = path.Substring(i + 1);
            }
            else
            {
                packageName = path;
                path = "";
            }
            UmlElement element = GetElement(packageName);
            if (element == null)
            {
                element = new UmlPackage();
                element.Name = packageName;
                AddElement(element);
            }

            if (!(element is UmlPackage))
                throw new Exception("Ambiguous element name");

            if (path.Length > 0)
                return (element as UmlPackage).GetPackage(path);
            else
                return element as UmlPackage;
        }

        public override void AddElement(UmlElement element)
        {
            Childs.Add(element);
        }

        public static UmlPackage CreateBuiltinSystemPackage()
        {
            UmlPackage p = new UmlPackage();
            p.Name = "System";
            EventService.StopBroadcasting();
            p.AddElement(new UmlType("Boolean"));
            p.AddElement(new UmlType("Byte"));
            p.AddElement(new UmlType("SByte"));
            p.AddElement(new UmlType("Char"));
            p.AddElement(new UmlType("Decimal"));
            p.AddElement(new UmlType("Double"));
            p.AddElement(new UmlType("Single"));
            p.AddElement(new UmlType("Int32"));
            p.AddElement(new UmlType("UInt32"));
            p.AddElement(new UmlType("Int64"));
            p.AddElement(new UmlType("UInt64"));
            p.AddElement(new UmlType("Object"));
            p.AddElement(new UmlType("Int16"));
            p.AddElement(new UmlType("UInt16"));
            p.AddElement(new UmlType("String"));
            EventService.ResumeBroadcasting();
            return p;
        }

        public void Sort()
        {
            EventService.StopBroadcasting();
            List<UmlElement> packageList = new List<UmlElement>(this.Childs.Where(e => e is UmlPackage).OrderBy(e => e.Name));
            List<UmlElement> otherList = new List<UmlElement>(this.Childs.Where(e => !(e is UmlPackage)).OrderBy(e => e.Name));
            foreach (UmlPackage p in packageList)
                p.Sort();

            Childs.Clear();
            foreach (UmlElement e in packageList) Childs.Add(e);
            foreach (UmlElement e in otherList) Childs.Add(e);
            EventService.ResumeBroadcasting();
        }
    }
}
